﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Spectrum
{
    /// <summary>
    /// 广东省性能设计规程反应谱
    /// </summary>
    public class GDCodeSpectrum: SpectSet
    {
        /// <summary>
        /// 特征周期值
        /// </summary>
        private double ModelTg { set; get; }

        /// <summary>
        /// 地震影响系数最大值
        /// </summary>
        private double ModelAfaMax { set; get; }

        /// <summary>
        /// 场地类别 用于判断峰值加速度
        /// </summary>
        public string GDSoilCondition { set; get; }

        /// <summary>
        /// 斜率调整系数
        /// </summary>
        private double GetFactor(double period)
        {
            if (period < 3.5)
                return 1 + (0.05 - this.DampingRatio) / (0.1 + 1.2 * this.DampingRatio);
            //else if (period < 3.7)
            //    return 1 + (0.05 - this.DampingRatio) / (0.1 + 
            //        (1.2 + 1.25 * (period - 3.5)) * this.DampingRatio);
            else return 1 + (0.05 - this.DampingRatio) / (0.1 + 1.45 * this.DampingRatio);
        }

        /// <summary>
        /// 根据周期计算影响系数
        /// </summary>
        /// <param name="period"></param>
        /// <returns></returns>
        private double PeriodToAfa(double period)
        {
            //周期小于零不存在
            if (period < 0) return -1;
            //0到0.1
            else if (period <= 0.1)
            {
                return (this.GetFactor(period) * this.ModelAfaMax - 0.45 * this.ModelAfaMax) / 0.1 * period 
                    + 0.45 * this.ModelAfaMax;
            }
            //0.1到Tg
            else if (period <= this.ModelTg) return this.GetFactor(period) * this.ModelAfaMax;
            //Tg到5Tg
            else if (period <= 3.5)
                return (this.ModelTg / period) * this.GetFactor(period) * this.ModelAfaMax;
            //6s外
            else return (this.ModelTg * 3.5 / Math.Pow(period, 2)) * this.GetFactor(period) * this.ModelAfaMax;
        }

        /// <summary>
        /// 场地影响系数
        /// </summary>
        private double Si
        {
            get
            {
                switch (this.GDSoilCondition)
                {
                    case "II": return 0.9;
                    case "III": return 1.0;
                    case "IV": return 1.1;
                    default: return 0.8;
                }
            }
        }

        /// <summary>
        /// 正则化
        /// </summary>
        /// <returns></returns>
        public override void Regularization()
        {
            //反应谱折减
            this.SpectrumAmplitude((float)this.GetReductionFactor());
        }

        /// <summary>
        /// 折减到1PGA所采用的折减系数
        /// </summary>
        /// <returns></returns>
        public override double GetReductionFactor()
        {
            //默认加速度为影响系数的440倍(cm)
            var pga = this.ModelAfaMax * 9.8 / 2.5 * 100;
            //根据场地类别枚举
            switch (this.GDSoilCondition)
            {
                case "II":
                    {
                        if (this.ModelAfaMax == 0.04) pga = 16;
                        else if (this.ModelAfaMax == 0.08) pga = 32;
                        else if (this.ModelAfaMax == 0.16) pga = 63;

                        else if (this.ModelAfaMax == 0.12) pga = 50;
                        else if (this.ModelAfaMax == 0.23) pga = 100;
                        else if (this.ModelAfaMax == 0.34) pga = 150;
                        else if (this.ModelAfaMax == 0.45) pga = 200;
                        else if (this.ModelAfaMax == 0.68) pga = 300;
                        else if (this.ModelAfaMax == 0.90) pga = 400;

                        else if (this.ModelAfaMax == 0.28) pga = 125;
                        else if (this.ModelAfaMax == 0.50) pga = 220;
                        else if (this.ModelAfaMax == 0.72) pga = 310;
                        else if (this.ModelAfaMax == 1.20) pga = 510;
                        else if (this.ModelAfaMax == 1.40) pga = 620;

                        else if (0.114 <= this.ModelAfaMax && this.ModelAfaMax <= 0.126) pga = 50;
                        else if (0.219 <= this.ModelAfaMax && this.ModelAfaMax <= 0.242) pga = 100;
                        else if (0.323 <= this.ModelAfaMax && this.ModelAfaMax <= 0.357) pga = 150;
                        else if (0.428 <= this.ModelAfaMax && this.ModelAfaMax <= 0.473) pga = 200;
                        else if (0.646 <= this.ModelAfaMax && this.ModelAfaMax <= 0.714) pga = 300;
                        else if (0.855 <= this.ModelAfaMax && this.ModelAfaMax <= 0.945) pga = 400;

                        break;
                    }
                case "III":
                case "IV":
                    {
                        if (this.ModelAfaMax == 0.05) pga = 20;
                        else if (this.ModelAfaMax == 0.10) pga = 39;
                        else if (this.ModelAfaMax == 0.15) pga = 61;
                        else if (this.ModelAfaMax == 0.20) pga = 77;


                        else if (this.ModelAfaMax == 0.13) pga = 55;
                        else if (this.ModelAfaMax == 0.25) pga = 110;
                        else if (this.ModelAfaMax == 0.37) pga = 165;
                        else if (this.ModelAfaMax == 0.50) pga = 220;
                        else if (this.ModelAfaMax == 0.75) pga = 330;
                        else if (this.ModelAfaMax == 1.00) pga = 440;

                        else if (this.ModelAfaMax == 0.14) pga = 55;
                        else if (this.ModelAfaMax == 0.28) pga = 110;
                        else if (this.ModelAfaMax == 0.42) pga = 165;
                        else if (this.ModelAfaMax == 0.56) pga = 220;
   
                        else if (this.ModelAfaMax == 0.31) pga = 138;
                        else if (this.ModelAfaMax == 0.35) pga = 138;
                        else if (this.ModelAfaMax == 0.55) pga = 242;
                        else if (this.ModelAfaMax == 0.62) pga = 242;
                        else if (this.ModelAfaMax == 0.79) pga = 341;
                        else if (this.ModelAfaMax == 0.87) pga = 341;
                        else if (this.ModelAfaMax == 1.12) pga = 440;
                        else if (this.ModelAfaMax == 1.32) pga = 560;
                        else if (this.ModelAfaMax == 1.54) pga = 682;

                        else if (0.124 <= this.ModelAfaMax && this.ModelAfaMax <= 0.137) pga = 55;
                        else if (0.238 <= this.ModelAfaMax && this.ModelAfaMax <= 0.263) pga = 110;
                        else if (0.351 <= this.ModelAfaMax && this.ModelAfaMax <= 0.389) pga = 165;
                        else if (0.475 <= this.ModelAfaMax && this.ModelAfaMax <= 0.525) pga = 220;
                        else if (0.713 <= this.ModelAfaMax && this.ModelAfaMax <= 0.788) pga = 330;
                        else if (0.950 <= this.ModelAfaMax && this.ModelAfaMax <= 1.05) pga = 440;

                        break;
                    }

                default:
                    {
                        if (this.ModelAfaMax == 0.04) pga = 14;
                        else if (this.ModelAfaMax == 0.07) pga = 28;
                        else if (this.ModelAfaMax == 0.14) pga = 56;

                        else if (this.ModelAfaMax == 0.11) pga = 45;
                        else if (this.ModelAfaMax == 0.20) pga = 90;
                        else if (this.ModelAfaMax == 0.30) pga = 135;
                        else if (this.ModelAfaMax == 0.40) pga = 180;
                        else if (this.ModelAfaMax == 0.60) pga = 270;
                        else if (this.ModelAfaMax == 0.80) pga = 360;

                        

                        else if (this.ModelAfaMax == 0.25) pga = 113;
                        else if (this.ModelAfaMax == 0.45) pga = 198;
                        else if (this.ModelAfaMax == 0.65) pga = 279;
                        else if (this.ModelAfaMax == 0.80) pga = 360;
                        else if (this.ModelAfaMax == 1.08) pga = 459;
                        else if (this.ModelAfaMax == 1.26) pga = 558;

                        else if (0.105 <= this.ModelAfaMax && this.ModelAfaMax <= 0.116) pga = 45;
                        else if (0.190 <= this.ModelAfaMax && this.ModelAfaMax <= 0.210) pga = 90;
                        else if (0.285 <= this.ModelAfaMax && this.ModelAfaMax <= 0.315) pga = 135;
                        else if (0.380 <= this.ModelAfaMax && this.ModelAfaMax <= 0.420) pga = 180;
                        else if (0.570 <= this.ModelAfaMax && this.ModelAfaMax <= 0.630) pga = 270;
                        else if (0.760 <= this.ModelAfaMax && this.ModelAfaMax <= 0.840) pga = 360;

                        break;
                    }
            }
            //确定折减系数
            return 9.8E2 / (pga * this.PGAMultiplier) ;
        }

        /// <summary>
        /// 根据周期计算影响系数
        /// </summary>
        /// <param name="period"></param>
        /// <returns></returns>
        public override double GetAfaByPeriod(double period)
        {
            return this.PeriodToAfa(period);
        }

        /// <summary>
        /// 空的构造函数
        /// </summary>
        public GDCodeSpectrum() : base()
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public GDCodeSpectrum(double tg, double afaMax, double dampRatio, double periodLength, double deltaPeriod,
            string soilCondition) : base()
        {
            //设定信息
            this.ModelAfaMax = afaMax;
            this.ModelTg = tg;
            this.DampingRatio = dampRatio;
            this.PeriodLength = (float)periodLength;
            this.DeltaPeriod = (float)deltaPeriod;
            this.GDSoilCondition = soilCondition;
            //添加反应谱值
            for (float period = this.DeltaPeriod; period <= periodLength; period += this.DeltaPeriod)
                this.Add(period, (float)this.PeriodToAfa(period));
        }
    }
}
